TDD测试驱动开发学习(1)
前言
说到测试驱动,就好像各种模式一样,你知道她好,但是总是没有好好的去坚持,去实施,这事,就和女人的减肥事业一样,磨练人的意志。
让我重新开始决定好好学习TDD原因,最基础的时间条件来说,我最近是比较空闲,处于项目空档期;另外,这几天在看美剧《硅谷》(SILICON VALLEY)。其中有一集就是,有个小毛孩把男主的程序数据库全毁了,男主花了好大心事修复,而最后一个镜头就是,他的所有测试用例,一排绿灯通过,这下,他才开始放心揍那个高科技骗子。虽然这个镜头只有一秒不到的时间,但这个镜头在我还算幼小的心灵,烙下了一个我要好好学TDD的念头,哈哈哈O(∩_∩)O哈哈~
从0开始
我follow的这本书是测试驱动开发的艺术, 以下是我根据书中内容,一步一步敲打代码的步骤总结,只为了,让自己梳理一下。
Android studio 添加 junit 测试
当然,书里面没有讲怎么在 Android studio 集成IDE中添加junit测试,下面是我摸索的结果。
创建一个Android项目,这里,也可以不是,随便java项目也可以,我们只是做一个基本的java Junit测试的demo程序而已。我创建的是一个Android的项目按AS的模板默认设置就可以;默认的项目目录结构如下图(采用project视图):
打开
build.gradle
文件,将junit:junit:4.12加入编译1
2
3
4
5
6dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'junit:junit:4.12'
testCompile 'junit:junit:4.12'
}然后点击
Sync Project with Grandle files
的那个图标按钮,这个时候,我们就可以在代码中访问@Test
了package com.example.lynn.myapplication; import org.junit.Test; /** * Created by lynn8570 on 2015-9-16. * mail: lynn8570@gmail.com */ public class TestDemo { @Test public void testOne() throws Exception{ } }
告诉编译器,你的测试代码在哪里,一般android项目的默认测试代码放在
/src/androidTest/java
中,因此我们需要在gradle文件中添加如下内容:android { sourceSets{ test { java.srcDir file('src/androidTest/java') } } }
由于我们只是运行junit测试,而android默认的测试是
Android Instrumentation Tests
,所以需要在运行测试的时候,点击Build Variants
(一般在左下角),将Test Artifact
设置为Unit Tests
。随便写一个测试看下我们的测试可否运行,代码如下:
@Test public void testOne() throws Exception{ assertNotNull(new Object()); }
配置测试运行参数,在
Run/Debug Configurations
对话框中,点击“+”号,添加Junit运行配置。你可以只运行一个class或者运行package下所有的包。运行测试,测试通过配置完成,event log输出如下内容的话,表示前期准备OK
13:46:00 Compilation completed successfully in 4s 393ms 13:46:00 Tests Passed: 1 passed in 0.032 s
可能会遇到一些错误
默认的ApplicationTestCase未删掉,因为AS默认创建的Android项目是有一个默认的ApplicationTestCase测试,由于我们将build variantants中的Test Artifact改为Unit Test,会造成报错如下:
Exception in thread "main" java.lang.NoClassDefFoundError: android/test/ApplicationTestCase at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:800) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:425) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:270) at com.intellij.junit4.JUnit4TestRunnerUtil.loadTestClass(JUnit4TestRunnerUtil.java:302) at com.intellij.junit4.JUnit4TestRunnerUtil.appendTestClass(JUnit4TestRunnerUtil.java:286) at com.intellij.junit4.JUnit4TestRunnerUtil.buildRequest(JUnit4TestRunnerUtil.java:80) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:39) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Caused by: java.lang.ClassNotFoundException: android.test.ApplicationTestCase at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:425) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ... 25 more
如果这样,请删除默认的ApplicationTestCase
如果运行时,提示错误信息:
Error running TestDemo: Class 'com.example.lynn.myapplication.TestDemo' not found in module 'app'
检查是否添加了
sourceSets{ test { java.srcDir file('src/androidTest/java') } }
总结
通过上面的环境准备,基本就可以按照书本里面的步骤开始一步步敲代码啦~~
至此书本上的第一个demo演练已经过了一遍,主要是模板解析的一个演示程序,在不断写测试代码,完成功能,重构优化的一轮轮中,通过测试代码作为基本保障,让程序代码不断的完善。